﻿using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using Synology.AudioStationApi;
using WMPLib;

namespace PartTwo
{
    public class PlayerService : IPlayerService
    {
        private readonly AudioStationSession _session;

        private static WMPLib.WindowsMediaPlayer _player;
        private ObservableCollection<SynoTrack> _playlist = new ObservableCollection<SynoTrack>();
        private ObservableCollection<SynoTrack> _history = new ObservableCollection<SynoTrack>();
        private bool _isPlaying = false;
        private Timer _timer;
        public PlayerService(AudioStationSession session)
        {
            _player = new WindowsMediaPlayer();
            _player.PlayStateChange += MediaEnded;
            

            _session = session;

            //TODO : Replace time-based buffering with size-based.
            _timer = new Timer(1000);
            _timer.AutoReset = false;

            _timer.Elapsed += (o, e) =>
                Application.Current.Dispatcher.Invoke(new Action(() =>
                                                               {
                                                                   _isPlaying = true;
                                                                   _player.controls.play();   
                                                               }
                    ));
        }

        public void PlayTrack(SynoTrack trackInfo)
        {
            if (_isPlaying)
            {
                //_mediaElement.Stop();
                _isPlaying = false;
            }

            var response = _session.GetResource(trackInfo.Res);

            string tempFilePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".mp3");
            var stream = File.Open(tempFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);

            DownloadToTemporaryFile(response.GetResponseStream(), response.ContentLength, stream);
            _player.URL = tempFilePath;


            _timer.Start();


            
        }

        public void AddTrackToPlaylist(SynoTrack trackinfo)
        {
            _playlist.Add(trackinfo);
            if (!_isPlaying)
            {
                PlayTrack(_playlist.First());
            }
        }

        public ObservableCollection<SynoTrack> Playlist
        {
            get
            {
                return _playlist;
            }
        }

        private void MediaEnded(int newState)
        {
            if ((WMPPlayState)newState == WMPPlayState.wmppsStopped)
            {
                _isPlaying = false;
                if (_playlist.Count > 0)
                {
                    var nextTrack = _playlist.First();
                    _playlist.Remove(nextTrack);
                    _history.Add(nextTrack);
                    PlayTrack(nextTrack);
                }
            }


        }

        private void DownloadToTemporaryFile(Stream stream, long contentLength, Stream targetStream)
        {
            int bufferSize = 1024;
            var buffer = new byte[bufferSize];

            stream.BeginRead(buffer, 0, buffer.Length, Callback, new Tuple<Stream, long, Stream, byte[]>(stream, contentLength, targetStream, buffer));
        }

        private void Callback(IAsyncResult ar)
        {
            var args = (Tuple<Stream, long, Stream, byte[]>)ar.AsyncState;
            var sourceStream = args.Item1;
            var bytesLeft = args.Item2;
            var targetStream = args.Item3;
            var buffer = args.Item4;
            var readCount = sourceStream.EndRead(ar);
            bytesLeft = bytesLeft - readCount;

            targetStream.Write(buffer, 0, readCount);

            if (bytesLeft > 0)
            {
                sourceStream.BeginRead(buffer, 0, buffer.Length, Callback, new Tuple<Stream, long, Stream, byte[]>(sourceStream, bytesLeft, targetStream, buffer));
            }
            else
            {

            }

        }
    }
}